﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;

namespace SmartMathLibrary.Management.Pipe
{
    /// <summary>
    /// This class allows to build up a pipeline, where unspecified objects can be modified.
    /// </summary>
    [Serializable]
    public class StepByStepPipe
    {
        /// <summary>
        /// The pipelinevalues of the pipe.
        /// </summary>
        private PipeValueCollection pipeValues;

        /// <summary>
        /// The pipeitems of the pipe.
        /// </summary>
        private List<AbstractPipeItem> pipeItems;

        /// <summary>
        /// Initializes a new instance of the <see cref="StepByStepPipe"/> class.
        /// </summary>
        public StepByStepPipe()
        {
            this.pipeValues = new PipeValueCollection();
            this.pipeItems = new List<AbstractPipeItem>();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="StepByStepPipe"/> class.
        /// </summary>
        /// <param name="items">The pipeitems to add to the current pipe.</param>
        public StepByStepPipe(AbstractPipeItem[] items)
        {
            if (items == (AbstractPipeItem[]) null)
            {
                throw new ArgumentNullException("items");
            }

            this.pipeItems = new List<AbstractPipeItem>();

            for (int i = 0; i < items.Length; i++)
            {
                this.pipeItems.Add(items[i]);
            }
        }

        /// <summary>
        /// Gets or sets the pipeitems of the current pipe.
        /// </summary>
        /// <value>The pipeitems of the current pipe.</value>
        public List<AbstractPipeItem> PipeItems
        {
            get { return pipeItems; }
            set { pipeItems = value; }
        }

        /// <summary>
        /// Gets or sets the pipevalues of the current pipe.
        /// </summary>
        /// <value>The pipevalues of the current pipe.</value>
        public PipeValueCollection PipeValues
        {
            get { return pipeValues; }
            set { pipeValues = value; }
        }

        /// <summary>
        /// Gets the number of pipeitems in the current pipe.
        /// </summary>
        /// <value>The number of pipeitems in the current pipe.</value>
        public int Count
        {
            get { return pipeItems.Count; }
        }

        /// <summary>
        /// Starts the interaction of the pipe.
        /// </summary>
        /// <param name="workingItems">The items, which should be modified by the pipe.</param>
        public void StartWork(Object[] workingItems)
        {
            int i = 0;
            object tempuri;

            for (int itemCounter = 0; itemCounter < this.pipeItems.Count; itemCounter++)
            {
                i = 0;
                this.pipeItems[i].RefreshPipeValues(ref this.pipeValues);

                while (i < workingItems.Length)
                {
                    tempuri = workingItems[i];
                    this.pipeItems[itemCounter].WorkOn(ref tempuri, i);
                    i++;
                }
            }
        }
    }
}